package studiodiva.portfolio.client.lib.lang;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import static studiodiva.portfolio.client.lib.lang.Lang.list;

import studiodiva.portfolio.client.lib.collections.GenericIterator;

public class TextImpl implements Text {

  private final StringBuilder value = new StringBuilder();

  public TextImpl(String... strings) {
    add(strings);
  }

  public Text add(String... strings) {
    for (String string : strings)
      value.append(string);
    return this;
  }

  public Text add(String string) {
    value.append(string);
    return this;
  }

  @Override
  public Text addLine() {
    return add("\n");
  }

  @Override
  public Text addSpace() {
    return add(" ");
  }

  public Appendable append(char c) throws IOException {
    return value.append(c);
  }

  public Appendable append(CharSequence csq) throws IOException {
    return value.append(csq);
  }

  public Appendable append(CharSequence csq, int start, int end) throws IOException {
    return value.append(csq, start, end);
  }

  public Text caseDown() {
    set(toString().toLowerCase());
    return this;
  }

  public Text caseUp(int index) {
    set(value.substring(0, index) + value.substring(index, index + 1).toUpperCase()
        + value.substring(index + 1, length()));
    return this;
  }

  public char charAt(int index) {
    return value.charAt(index);
  }

  public Text cut(int start, int end) {
    value.delete(start, end);
    return this;
  }

  public Text cutEnd(int length) {
    return cut(length() - length, length());
  }

  public Text cutStart(int length) {
    return cut(0, length);
  }

  public boolean isEmpty() {
    return value.length() == 0;
  }

  public Iterator<Character> iterator() {
    return new GenericIterator<Character>(length()) {
      @Override
      protected Character getValue() {
        return charAt(getIndex());
      }
    };
  }

  public int length() {
    return value.length();
  }

  public Text remove(String... strings) {
    String text = toString();
    for (String string : strings)
      text = text.replaceAll(string, "");
    set(text);
    return this;
  }

  public Text replace(String regex, String replace) {
    set(toString().replaceAll(regex, replace));
    return this;
  }

  public Text replaceEnd(String string) {
    cutEnd(string.length());
    add(string);
    return this;
  }

  public void set(CharSequence text) {
    clear();
    value.append(text);
  }

  public List<Text> split(String regex) {
    List<Text> split = list();
    for (String string : toString().split(regex))
      split.add(new TextImpl(string));
    return split;
  }

  public CharSequence subSequence(int start, int end) {
    return value.subSequence(start, end);
  }

  @Override
  public String toString() {
    return value.toString();
  }

  public Text trim() {
    set(toString().trim());
    return this;
  }

  private void clear() {
    value.delete(0, length());
  }
}
